/*-------------------------------------------------------------------------
 *
 * guc_tables.h
 *		GUC 使用的表的声明。
 *
 * 请参阅 src/backend/utils/misc/README 以获取设计说明。
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 *
 *	  src/include/utils/guc_tables.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef GUC_TABLES_H
#define GUC_TABLES_H 1

#include "utils/guc.h"

/*
 * GUC支持这些类型的变量:
 */
enum config_type
{
	PGC_BOOL,
	PGC_INT,
	PGC_REAL,
	PGC_STRING,
	PGC_ENUM
};

union config_var_val
{
	bool		boolval;
	int			intval;
	double		realval;
	char	   *stringval;
	int			enumval;
};

/*
 * GUC变量的实际值可以包括一个malloc'd不透明结构
 * "extra"，由其check_hook创建并由其assign_hook使用。
 */
typedef struct config_var_value
{
	union config_var_val val;
	void	   *extra;
} config_var_value;

/*
 * 帮助组织所有运行时选项以便于显示的分组。
 * 确保这与config.sgml中选项的分类方式一致！
 */
enum config_group
{
	UNGROUPED,					/* 用于pg_settings中不显示的选项 */
	FILE_LOCATIONS,
	CONN_AUTH_SETTINGS,
	CONN_AUTH_AUTH,
	CONN_AUTH_SSL,
	RESOURCES_MEM,
	RESOURCES_DISK,
	RESOURCES_KERNEL,
	RESOURCES_VACUUM_DELAY,
	RESOURCES_BGWRITER,
	RESOURCES_ASYNCHRONOUS,
	WAL_SETTINGS,
	WAL_CHECKPOINTS,
	WAL_ARCHIVING,
	WAL_RECOVERY,
	WAL_ARCHIVE_RECOVERY,
	WAL_RECOVERY_TARGET,
	REPLICATION_SENDING,
	REPLICATION_PRIMARY,
	REPLICATION_STANDBY,
	REPLICATION_SUBSCRIBERS,
	QUERY_TUNING_METHOD,
	QUERY_TUNING_COST,
	QUERY_TUNING_GEQO,
	QUERY_TUNING_OTHER,
	LOGGING_WHERE,
	LOGGING_WHEN,
	LOGGING_WHAT,
	PROCESS_TITLE,
	STATS_MONITORING,
	STATS_CUMULATIVE,
	AUTOVACUUM,
	CLIENT_CONN_STATEMENT,
	CLIENT_CONN_LOCALE,
	CLIENT_CONN_PRELOAD,
	CLIENT_CONN_OTHER,
	LOCK_MANAGEMENT,
	COMPAT_OPTIONS_PREVIOUS,
	COMPAT_OPTIONS_CLIENT,
	ERROR_HANDLING_OPTIONS,
	PRESET_OPTIONS,
	CUSTOM_OPTIONS,
	DEVELOPER_OPTIONS
};

/*
 * 用于保存变量在未提交的事务更改之前状态的栈条目
 */
typedef enum
{
	/* 这几乎是GucAction，但我们需要一个第四状态用于SET+LOCAL */
	GUC_SAVE,					/* 由函数 SET 选项引起的条目 */
	GUC_SET,					/* 由简单的 SET 命令引起的条目 */
	GUC_LOCAL,					/* 由 SET LOCAL 命令引起的条目 */
	GUC_SET_LOCAL				/* 由 SET 然后 SET LOCAL 引起的条目 */
} GucStackState;

typedef struct guc_stack
{
	struct guc_stack *prev;		/* 先前的堆栈项（如果有的话） */
	int			nest_level;		/* 我们进入时的嵌套深度 */
	GucStackState state;		/* 参见上面的枚举 */
	GucSource	source;			/* 先前值的来源 */
	/* 掩码值的来源必须是 PGC_S_SESSION，因此无需存储它 */
	GucContext	scontext;		/* 设置先前值的上下文 */
	GucContext	masked_scontext;	/* 设置掩码值的上下文 */
	Oid			srole;			/* 设置先前值的角色 */
	Oid			masked_srole;	/* 设置掩码值的角色 */
	config_var_value prior;		/* 变量的先前值 */
	config_var_value masked;	/* GUC_SET_LOCAL 条目中的 SET 值 */
} GucStack;

/*
 * 适用于所有类型变量的通用字段
 *
 * 短描述应少于 80 个字符。一些
 * 应用程序可能还会使用长描述，并将其附加到
 * 短描述后面。（由换行符或'. '分隔）
 *
 * srole 是设置当前值的角色，如果值来自内部来源
 * 或配置文件，则为 BOOTSTRAP_SUPERUSERID。重置
 * srole（通常是 BOOTSTRAP_SUPERUSERID，但不总是如此）也是如此。
 *
 * 请注意，sourcefile/sourceline 保留在这里，而不是推送到堆栈
 * 值中，尽管原则上它们与某些堆栈值相关，如果
 * 活动值是会话或事务本地的。这是为了避免膨胀
 * 堆栈条目。我们知道它们仅在 source == PGC_S_FILE
 * 时是相关的。
 */
struct config_generic
{
	/* 常量字段，必须在初始值中正确设置： */
	const char *name;			/* 变量名称 - 必须是第一个 */
	GucContext	context;		/* 设置变量所需的上下文 */
	enum config_group group;	/* 帮助按功能组织变量 */
	const char *short_desc;		/* 此变量目的的简短描述 */
	const char *long_desc;		/* 此变量目的的长期描述 */
	int			flags;			/* 标志位，见 guc.h */
	/* 变量字段，在运行时初始化： */
	enum config_type vartype;	/* 变量类型（仅在启动时设置） */
	int			status;			/* 状态位，见下文 */
	GucSource	source;			/* 当前实际值的来源 */
	GucSource	reset_source;	/* reset_value 的来源 */
	GucContext	scontext;		/* 设置当前值的上下文 */
	GucContext	reset_scontext; /* 设置重置值的上下文 */
	Oid			srole;			/* 设置当前值的角色 */
	Oid			reset_srole;	/* 设置重置值的角色 */
	GucStack   *stack;			/* 堆栈先前的值 */
	void	   *extra;			/* 当前实际值的“额外”指针 */
	char	   *last_reported;	/* 如果变量是 GUC_REPORT，则值是上次发送给客户端的值
								 * （如果尚未发送，则为 NULL） */
	char	   *sourcefile;		/* 当前设置来自的文件（如果未在配置文件中设置，则为 NULL） */
	int			sourceline;		/* 源文件中的行 */
};

/* 状态字段中的位值 */
#define GUC_IS_IN_FILE		0x0001	/* 在配置文件中找到它 */
/*
 * 注意：GUC_IS_IN_FILE 位是 ProcessConfigFile 的瞬态状态。
 * 不要假设它的值在其他地方代表有用的信息。
 */
#define GUC_PENDING_RESTART 0x0002	/* 变更的值尚不能应用 */
#define GUC_NEEDS_REPORT	0x0004	/* 新值必须报告给客户端 */


/* 针对特定变量类型的 GUC 记录 */

struct config_bool
{
	struct config_generic gen;
	/* 常量字段，必须在初始值中正确设置： */
	bool	   *variable;
	bool		boot_val;
	GucBoolCheckHook check_hook;
	GucBoolAssignHook assign_hook;
	GucShowHook show_hook;
	/* 变量字段，在运行时初始化： */
	bool		reset_val;
	void	   *reset_extra;
};

struct config_int
{
	struct config_generic gen;
	/* 常量字段，必须在初始值中正确设置： */
	int		   *variable;
	int			boot_val;
	int			min;
	int			max;
	GucIntCheckHook check_hook;
	GucIntAssignHook assign_hook;
	GucShowHook show_hook;
	/* 变量字段，在运行时初始化： */
	int			reset_val;
	void	   *reset_extra;
};

struct config_real
{
	struct config_generic gen;
	/* 常量字段，必须在初始值中正确设置： */
	double	   *variable;
	double		boot_val;
	double		min;
	double		max;
	GucRealCheckHook check_hook;
	GucRealAssignHook assign_hook;
	GucShowHook show_hook;
	/* 变量字段，在运行时初始化： */
	double		reset_val;
	void	   *reset_extra;
};

/*
 * 关于字符串 GUC 的备注：boot_val 允许为 NULL，这导致
 * reset_val 和实际变量值 (*variable) 也为 NULL。
 * 然而，后续无法使用 set_config_option 或任何其他 GUC API 设置 NULL 值。
 * 此外，GUC API，如 SHOW，将以空字符串显示 NULL 值。
 * 选择使用 NULL boot_val 的调用者应在启动时稍后覆盖该设置，
 * 否则要小心 NULL 的语义在可见上与空字符串不同。
 */
struct config_string
{
	struct config_generic gen;
	/* 常量字段，必须在初始值中正确设置： */
	char	  **variable;
	const char *boot_val;
	GucStringCheckHook check_hook;
	GucStringAssignHook assign_hook;
	GucShowHook show_hook;
	/* 变量字段，在运行时初始化： */
	char	   *reset_val;
	void	   *reset_extra;
};

struct config_enum
{
	struct config_generic gen;
	/* 常量字段，必须在初始值中正确设置： */
	int		   *variable;
	int			boot_val;
	const struct config_enum_entry *options;
	GucEnumCheckHook check_hook;
	GucEnumAssignHook assign_hook;
	GucShowHook show_hook;
	/* 变量字段，在运行时初始化： */
	int			reset_val;
	void	   *reset_extra;
};

/* 与上述枚举以及 guc.h 对应的常量表 */
extern PGDLLIMPORT const char *const config_group_names[];
extern PGDLLIMPORT const char *const config_type_names[];
extern PGDLLIMPORT const char *const GucContext_Names[];
extern PGDLLIMPORT const char *const GucSource_Names[];

/* 获取当前设置的变量 */
extern struct config_generic **get_guc_variables(void);

extern void build_guc_variables(void);

/* 在枚举选项中搜索 */
extern const char *config_enum_lookup_by_value(struct config_enum *record, int val);
extern bool config_enum_lookup_by_name(struct config_enum *record,
									   const char *value, int *retval);
extern struct config_generic **get_explain_guc_options(int *num);

#endif							/* GUC_TABLES_H */
